﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.VisualStudio.Modeling;
using VsxFactory.Modeling.VisualStudio;

namespace VsxFactory.Modeling.Strategies.Rules
{
    public class ExpressionEvaluator
    {
        private static Regex regex;
        private ModelElement source;
        private string forcedName;

        static ExpressionEvaluator()
        {
            regex = new Regex(@"\{(?<Expression>[^\}]+)\}", RegexOptions.Singleline | RegexOptions.Compiled);
        }

        public ExpressionEvaluator(ModelElement mel, string forcedName=null)
        {
            System.Diagnostics.Contracts.Contract.Requires(mel != null);
            source = mel;
            this.forcedName = forcedName;
        }

        public string Evaluate(string expression)
        {
            return regex.Replace(expression, new MatchEvaluator(Evaluate));
        }

        private string Evaluate(Match match)
        {
            string str = match.Groups["Expression"].Value;
            object source = this.source;
            foreach (string str2 in str.Split(new char[] { '/' }))
            {
                source = this.DoEvaluate(source, str2);
            }
            if (source == null)
            {
                return string.Empty;
            }
            return Utils.NormalizeName( source.ToString());
        }

        private object DoEvaluate(object source, string propertyName)
        {
            if (source == null)
                return null;

            if (propertyName == "Name" && forcedName != null)
                return forcedName;

            ModelElement mel = source as ModelElement;
            var property = mel.GetDomainClass().FindDomainProperty(propertyName, true);
            if (property == null)
                return null;
            return property.GetValue(mel);
        }
    }
}
